package com.idea.relax.log.trace;

import com.idea.relax.log.constant.PropsConstant;
import com.idea.relax.log.support.utils.MDCUtil;
import com.idea.relax.log.support.utils.StringUtil;
import lombok.AllArgsConstructor;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;

/**
 * @className: TrackerFilter
 * @description: 负责增加Trace属性的过滤器
 * @author: salad
 * @date: 2023/1/9
 **/
@AllArgsConstructor
public class TrackerFilter implements Filter {

    private final ITraceIdGenerator traceIdGenerator;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        boolean ret = setTraceAttribute(servletRequest);
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            if (ret) {
                MDCUtil.removes(Arrays.asList(PropsConstant.TRACE_ID, PropsConstant.REQ_SOURCE, PropsConstant.ENTRANCE_URI));
            }
        }
    }

    private boolean setTraceAttribute(ServletRequest servletRequest) {
        if (servletRequest instanceof HttpServletRequest) {
            String traceId = ((HttpServletRequest) servletRequest).getHeader(PropsConstant.TRACE_ID_HEADER);
            String reqSource = ((HttpServletRequest) servletRequest).getHeader(PropsConstant.REQ_SOURCE_HEADER);
            String entranceUri = ((HttpServletRequest) servletRequest).getHeader(PropsConstant.ENTRANCE_URI_HEADER);

            if (StringUtil.isBlank(traceId)) {
                traceId = traceIdGenerator.generate();
            }
            //如果上游未传递，说明这是Http请求的进入
            if (StringUtil.isBlank(reqSource)) {
                reqSource = ReqSource.HTTP.getName();
            }

            if (StringUtil.isBlank(entranceUri)) {
                entranceUri = ((HttpServletRequest) servletRequest).getRequestURI();
            }

            MDCUtil.puts(Arrays.asList(PropsConstant.TRACE_ID, PropsConstant.REQ_SOURCE, PropsConstant.ENTRANCE_URI),
                    traceId, reqSource, entranceUri);

            return true;
        }
        return false;
    }

}
